﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Activation;
using System.ServiceModel.Routing;
using System.ServiceModel;
using System.ServiceModel.Description;
using HomeFramework.Model;
using System.ServiceModel.Dispatcher;

namespace HomeFramework.Services
{
    public class HomeFrameworkServiceFactory : ServiceHostFactory
    {
        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            if (string.IsNullOrEmpty(constructorString))
                throw new ArgumentException("constructorString empty!");
            else if (constructorString.Contains(typeof(HomeFrameworkService).FullName))
                return newHomeFrameworkServiceHost(baseAddresses);
            else if (constructorString.Contains(typeof(RoutingService).FullName))
                return newHomeFrameworkRoutingServiceHost(baseAddresses);
            else
                throw new ArgumentException("constructorString wrong!");
        }

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            if (serviceType.FullName == typeof(HomeFrameworkService).FullName)
                return newHomeFrameworkServiceHost(baseAddresses);
            else if (serviceType.FullName == typeof(RoutingService).FullName)
                return newHomeFrameworkRoutingServiceHost(baseAddresses);
            else
                throw new ArgumentException("constructorString wrong!");
        }

        internal static ServiceHost newHomeFrameworkServiceHost(Uri[] baseAddresses)
        {
            var h = new ServiceHost(typeof(HomeFrameworkService), baseAddresses);
            if (!h.Description.Behaviors.Contains(typeof(ServiceDebugBehavior)))
                h.Description.Behaviors.Add(new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });

            h.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });

            var binding = new NetNamedPipeBinding();
            h.AddServiceEndpoint(typeof(IHomeFrameworkService), binding, "");
            h.Description.Behaviors.Add(HomeFrameworkBehavior.Instance);
            return h;
        }

        //private const string HomeFrameworkServicePath = "InnerService.svc";
        internal static ServiceHost newHomeFrameworkRoutingServiceHost(Uri[] baseAddresses)
        {
            var clientBinding = new NetNamedPipeBinding();

            if (baseAddresses.FirstOrDefault(x => x.Scheme == "net.pipe") == null)
                throw new ArgumentException("No net.pipe binding available to use!");


            //var clientPath = baseAddresses.SingleOrDefault(x=>x.Scheme=="net.pipe");

            //if (clientPath == null)
            //    throw new ArgumentException("No net.pipe binding available to use!");
            //else
            //    clientPath = new Uri(clientPath.AbsoluteUri.Replace(clientPath.Segments.Last(), HomeFrameworkServicePath));

            var clientPath = Configuration.GetValue(Configuration.innerServicePath);

            var h = new ServiceHost(typeof(RoutingService), baseAddresses);

            ContractDescription contract = ContractDescription.GetContract(typeof(IRequestReplyRouter));
            ServiceEndpoint client = new ServiceEndpoint(contract, clientBinding, new EndpointAddress(clientPath));
            //create a new routing behavior
            List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>();
            endpointList.Add(client);
            RoutingConfiguration routingConfig = new RoutingConfiguration();
            routingConfig.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
            RoutingBehavior myRoutingBehavior = new RoutingBehavior(routingConfig);


            if (h.Description.Behaviors.Contains(typeof(RoutingBehavior)))
                h.Description.Behaviors.Remove(typeof(RoutingBehavior));

            if (h.Description.Behaviors.Contains(typeof(ServiceDebugBehavior)))
                h.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));

            if (!h.Description.Behaviors.Contains(typeof(HomeFrameworkBehavior)))
                h.Description.Behaviors.Remove(typeof(HomeFrameworkBehavior));

            h.Description.Behaviors.Add(myRoutingBehavior);
            h.Description.Behaviors.Add(new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
            h.Description.Behaviors.Add(new HomeFrameworkRouterBehavior());
            return h;
        }
    }
}